use glam::*;

use crate::grid;
use crate::view::*;

#[derive(Clone, Copy)]
pub struct MovingCursor {
    pub from: grid::Position,
    pub to: grid::Position,
    pub begin_from_frame: usize,
}

#[derive(Clone, Copy)]
pub enum Cursor {
    Tile(grid::Position),
    Moving(MovingCursor),
}

impl Cursor {
    pub fn at(position: grid::Position) -> Self {
        Cursor::Tile(position)
    }

    const MOVE_DURATION: f32 = 10.0;

    pub fn next_frame(self, next_frame_number: FrameNumber) -> Self {
        match self {
            Cursor::Tile(_) => self,
            Cursor::Moving(moving) => {
                if next_frame_number - moving.begin_from_frame == Cursor::MOVE_DURATION as usize {
                    Cursor::Tile(moving.to)
                } else {
                    Cursor::Moving(moving)
                }
            }
        }
    }

    pub fn move_offset(self, frame_number: FrameNumber, offset: grid::PositionOffset) -> Self {
        match self {
            Cursor::Tile(from) => {
                let new_position = offset.apply(from);
                if new_position == from {
                    self
                } else {
                    Cursor::Moving(MovingCursor {
                        begin_from_frame: frame_number,
                        to: new_position,
                        from,
                    })
                }
            }
            Cursor::Moving(..) => self,
        }
    }

    pub fn current_tile_offset(&self, frame_number: FrameNumber) -> Vec2 {
        match self {
            Cursor::Tile(pos) => vec2(pos.x() as f32, pos.y() as f32),
            Cursor::Moving(MovingCursor {
                from,
                to,
                begin_from_frame,
            }) => {
                let past_frame = frame_number - begin_from_frame;
                let past_ratio = past_frame as f32 / Cursor::MOVE_DURATION;
                vec2(
                    (to.x() as f32 - from.x() as f32) * past_ratio + from.x() as f32,
                    (to.y() as f32 - from.y() as f32) * past_ratio + from.y() as f32,
                )
            }
        }
    }

    pub fn focused_at(&self) -> grid::Position {
        match self {
            Cursor::Tile(to) => *to,
            Cursor::Moving(MovingCursor { to, .. }) => *to,
        }
    }
}
